#include "player.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_http_client.h"
#include "stb_vorbis.c"
#include "driver/i2s.h"

#define I2S_NUM I2S_NUM_0

static const char *TAG = "PLAYER";

static void i2s_init() {
    i2s_config_t i2s_config = {
        .mode = I2S_MODE_MASTER | I2S_MODE_TX,
        .sample_rate = 22050,
        .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
        .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
        .communication_format = I2S_COMM_FORMAT_STAND_I2S,
        .intr_alloc_flags = 0,
        .dma_buf_count = 8,
        .dma_buf_len = 1024,
        .use_apll = false,
        .tx_desc_auto_clear = true,
        .fixed_mclk = 0
    };

    i2s_pin_config_t pin_config = {
        .bck_io_num = 15,
        .ws_io_num = 16,
        .data_out_num = 17,
        .data_in_num = I2S_PIN_NO_CHANGE
    };

    i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL);
    i2s_set_pin(I2S_NUM, &pin_config);
}

static void play_pcm(int16_t *pcm_data, size_t pcm_data_size) {
    size_t bytes_written;
    i2s_write(I2S_NUM, pcm_data, pcm_data_size * sizeof(int16_t), &bytes_written, portMAX_DELAY);
}

static void decode_ogg(const uint8_t *ogg_data, size_t ogg_data_size) {
    int error;
    stb_vorbis *vorbis = stb_vorbis_open_memory(ogg_data, ogg_data_size, &error, NULL);
    if (vorbis == NULL) {
        ESP_LOGI(TAG, "打开OGG文件失败");
        return;
    }

    stb_vorbis_info info = stb_vorbis_get_info(vorbis);
    int num_channels = info.channels;
    int sample_rate = info.sample_rate;

    int samples = stb_vorbis_stream_length_in_samples(vorbis);
    int16_t *pcm_data = malloc(samples * num_channels * sizeof(int16_t));

    int sample_decoded = stb_vorbis_get_samples_short_interleaved(vorbis, num_channels, pcm_data, samples * num_channels);
    if (sample_decoded <= 0) {
        ESP_LOGI(TAG, "解析OGG文件失败");
        stb_vorbis_close(vorbis);
        free(pcm_data);
        return;
    }

    stb_vorbis_close(vorbis);
    play_pcm(pcm_data, sample_decoded * num_channels);
    free(pcm_data);
}

static void decode_and_play_ogg_data(const uint8_t *ogg_data, size_t ogg_data_size) {
    int error;
    stb_vorbis *vorbis = stb_vorbis_open_memory(ogg_data, ogg_data_size, &error, NULL);
    if (vorbis == NULL) {
        ESP_LOGI(TAG, "解析OGG文件失败");
        return;
    }

    stb_vorbis_info info = stb_vorbis_get_info(vorbis);
    int num_channels = info.channels;
    int sample_rate = info.sample_rate;

    int16_t pcm_data[2048];
    int samples_decoded;

    while ((samples_decoded = stb_vorbis_get_samples_short_interleaved(vorbis, num_channels, pcm_data, 2048)) > 0) {
        play_pcm(pcm_data, samples_decoded * num_channels);
    }

    stb_vorbis_close(vorbis);
}

static esp_err_t _http_event_handler(esp_http_client_event_t *evt) {
    static uint8_t *ogg_data = NULL;
    static size_t ogg_data_size = 0;
    static size_t ogg_data_capacity = 0;

    switch (evt->event_id) {
        case HTTP_EVENT_ERROR:
            ESP_LOGI(TAG, "HTTP_EVENT_ERROR");
            break;
        case HTTP_EVENT_ON_CONNECTED:
            ESP_LOGI(TAG, "HTTP_EVENT_ON_CONNECTED");
            break;
        case HTTP_EVENT_HEADER_SENT:
            ESP_LOGI(TAG, "HTTP_EVENT_HEADER_SENT");
            break;
        case HTTP_EVENT_ON_HEADER:
            ESP_LOGI(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
            break;
        case HTTP_EVENT_ON_DATA:
            ESP_LOGI(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
            if (!esp_http_client_is_chunked_response(evt->client)) {
                // 检查是否需要扩展缓冲区
                if (ogg_data_size + evt->data_len > ogg_data_capacity) {
                    ogg_data_capacity = ogg_data_size + evt->data_len;
                    uint8_t *new_data = realloc(ogg_data, ogg_data_capacity);
                    if (new_data == NULL) {
                        ESP_LOGE(TAG, "内存分配失败");
                        // 释放之前分配的内存
                        free(ogg_data);  
                        // 返回内存分配错误
                        return ESP_ERR_NO_MEM;  
                    }
                    // 更新指针
                    ogg_data = new_data;  
                }
                // 复制数据到缓冲区
                memcpy(ogg_data + ogg_data_size, evt->data, evt->data_len);
                ogg_data_size += evt->data_len;
            }
            break;
        case HTTP_EVENT_ON_FINISH:
            ESP_LOGI(TAG, "HTTP_EVENT_ON_FINISH");
            if (ogg_data != NULL) {
                // 处理解码和播放OGG数据
                decode_ogg(ogg_data, ogg_data_size);
                // 释放缓冲区
                free(ogg_data);
                // 重置指针
                ogg_data = NULL;
            }
            // 重置大小
            ogg_data_size = 0;
            // 重置容量
            ogg_data_capacity = 0;
            break;
        case HTTP_EVENT_DISCONNECTED:
            ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
            if (ogg_data != NULL) {
                // 释放缓冲区
                free(ogg_data);
                // 重置指针
                ogg_data = NULL;
            }
            // 重置大小
            ogg_data_size = 0;
            break;
        case HTTP_EVENT_REDIRECT:
            ESP_LOGI(TAG, "HTTP_EVENT_REDIRECT");
            break;
        default:
            ESP_LOGI(TAG, "Unhandled HTTP event: %d", evt->event_id);
            break;
    }
    return ESP_OK;
}

void player_init(void) {
    i2s_init();
}

void player_play(const char *url) {
    ESP_LOGI(TAG, "player_play接收到的URL：%s", url);
    if (url != NULL && strlen(url) > 0) {
        esp_http_client_config_t config = {
            .url = url,
            .event_handler = _http_event_handler,
            .timeout_ms = 5000
        };

        esp_http_client_handle_t client = esp_http_client_init(&config);
        if (client == NULL) {
            ESP_LOGE(TAG, "HTTP客户端初始化失败");
            return;
        }

        esp_err_t err = esp_http_client_perform(client);
        if (err != ESP_OK) {
            ESP_LOGE(TAG, "HTTP请求失败: %s", esp_err_to_name(err));
        }
        esp_http_client_cleanup(client);
    } else {
        ESP_LOGE(TAG, "接收到的URL无效");
    }
    
}

void audio_task(void *pvParameters) {
    // 获取传递的 URL 参数
    const char *url = (const char *)pvParameters; 
    ESP_LOGI(TAG, "接收到的URL：%s", url);

    player_play(url);

    // 复制 URL 字符串
    // char *url_copy = strdup(url);
    // if (url_copy != NULL) {
    //     // 播放音频
    //     player_play(url_copy);
    //     free(url_copy);
    // } else {
    //     ESP_LOGE("AUDIO_TASK", "URL 为 NULL");
    // }
    
    // 删除任务
    vTaskDelete(NULL);
}